#version 330 core

struct DirLight
{
	vec3 direction;
	vec3 color;
};

struct PointLight
{
	vec3 position;

	vec3 color;

	float constant;
	float linear;
	float quadratic;
};

struct Material
{
	float ambientStrength;
	float diffuseStrength;
	float specularStrength;
	float shininess;
};

in vec2 texPos;
in vec3 normal;
in vec3 fragPos;

out vec4 FragColor;

uniform DirLight dirLight;
uniform PointLight pointLight;

uniform Material material;

uniform vec3 ModelColor;

uniform vec3 viewPos;

vec3 DoDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
	vec3 lightDir = normalize(-light.direction);

	vec3 ambient = ModelColor * light.color * material.ambientStrength;

	float diff = max(dot(normal, lightDir), 0.0f);
	vec3 diffuse = diff * ModelColor * light.color * material.diffuseStrength;

	vec3 reflectDir = reflect(-lightDir, normal);
	float spec = pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
	vec3 specular = spec * ModelColor * light.color * material.specularStrength;

	return ambient + diffuse + specular;
}

vec3 DoPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
	vec3 lightDir = normalize(light.position - fragPos);
	float distance = length(light.position - fragPos);
	float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * distance * distance);

	vec3 ambient = ModelColor * light.color * material.ambientStrength;

	float diff = max(dot(lightDir, normal), 0.0f);
	vec3 diffuse = diff * ModelColor * light.color * material.diffuseStrength;

	vec3 reflectDir = reflect(-lightDir, normal);
	float spec = pow(max(dot(reflectDir, viewDir), 0.0f), material.shininess);
	vec3 specular = spec * ModelColor * light.color * material.specularStrength;

	return (ambient + diffuse + specular) * attenuation;
}

void main()
{
	vec3 norm = normalize(normal);
	vec3 viewDir = normalize(viewPos - fragPos);

	float alpha = vec4(1.0f, 1.0f, 1.0f, 1.0f).a;

	vec3 dirLightColor = DoDirLight(dirLight, norm, viewDir);
	vec3 pointLightColor = DoPointLight(pointLight, norm, fragPos, viewDir);

	FragColor = vec4(dirLightColor + pointLightColor, alpha);
}

